Skip to content

Fix RandGridDistortiond crash when transform is skipped#8788

Open
HeyangQin wants to merge 3 commits intoProject-MONAI:devfrom
HeyangQin:fix/rand-grid-distortiond-no-transform
Open

Fix RandGridDistortiond crash when transform is skipped#8788
HeyangQin wants to merge 3 commits intoProject-MONAI:devfrom
HeyangQin:fix/rand-grid-distortiond-no-transform

Conversation

@HeyangQin
Copy link

Summary

  • Fix AttributeError: 'int' object has no attribute 'numel' when RandGridDistortiond skips the transform (random probability not met)
  • Root cause: convert_to_tensor(d, ...) was called on the entire data dict, which fails when non-tensor metadata (ints, strings) is present
  • Fix: convert only the keyed tensor items via self.key_iterator(d), consistent with how other dict transforms handle the no-transform path

Test plan

  • Added test: dict with non-tensor metadata (extra_info=42, label_name="tumor") + prob=0.0 passes without error
  • All 4 RandGridDistortiond tests pass (3 existing + 1 new)
  • Integration: verify DataLoader with RandGridDistortiond and num_workers>0 no longer crashes

Fixes #8604

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 22, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6397bd45-0cc7-4949-81aa-822e3f40a8c9

📥 Commits

Reviewing files that changed from the base of the PR and between 68f7e2e and bf00db8.

📒 Files selected for processing (1)
  • tests/transforms/test_rand_grid_distortiond.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/transforms/test_rand_grid_distortiond.py

📝 Walkthrough

Walkthrough

Multiple dictionary-based spatial transforms were modified so they no longer call convert_to_tensor(d, ...) on the entire input mapping when first_key == (); instead they return the original mapping unchanged. For RandGridDistortiond.__call__, the non-transform branch (not self._do_transform) now iterates self.key_iterator(d) and calls convert_to_tensor(d[key], ...) per key, mutating d in-place and returning it. The transform path that performs random distortion remains unchanged. A unit test was added to verify metadata and image are preserved when prob=0.0. No public API declarations were changed.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly summarizes the main fix: preventing RandGridDistortiond crashes when the transform is skipped.
Description check ✅ Passed Description covers the bug, root cause, fix approach, test plan, and issue reference. Follows template structure with summary and test details.
Linked Issues check ✅ Passed Changes directly address issue #8604: convert keyed items only via key_iterator [#8604], preventing non-tensor metadata crashes in DataLoader collation.
Out of Scope Changes check ✅ Passed All changes are scoped to fix RandGridDistortiond no-transform path and add related tests. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
monai/transforms/spatial/dictionary.py (1)

2313-2315: Pre-existing convert_to_tensor(d, ...) remains for edge case.

When first_key == () (all keys missing), the entire dict is still converted. This matches other transforms (RandAffined, RandZoomd, etc.) but could cause issues with non-tensor metadata in that rare edge case. Consider addressing in a follow-up if needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@monai/transforms/spatial/dictionary.py` around lines 2313 - 2315, The branch
handling the edge case where first_key == () currently calls
convert_to_tensor(d, track_meta=get_track_meta()) which can inadvertently
convert non-tensor metadata; update this branch to avoid converting the entire
dict: either return the original dict unchanged or call convert_to_tensor only
on entries that are tensor-compatible (filter keys by type or use an
is_tensor_compatible check) and leave other metadata untouched. Modify the
first_key == () logic in dictionary.py to use the safer behavior (referencing
first_key, convert_to_tensor, and get_track_meta) so non-tensor metadata isn’t
transformed unexpectedly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@monai/transforms/spatial/dictionary.py`:
- Around line 2313-2315: The branch handling the edge case where first_key == ()
currently calls convert_to_tensor(d, track_meta=get_track_meta()) which can
inadvertently convert non-tensor metadata; update this branch to avoid
converting the entire dict: either return the original dict unchanged or call
convert_to_tensor only on entries that are tensor-compatible (filter keys by
type or use an is_tensor_compatible check) and leave other metadata untouched.
Modify the first_key == () logic in dictionary.py to use the safer behavior
(referencing first_key, convert_to_tensor, and get_track_meta) so non-tensor
metadata isn’t transformed unexpectedly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 44837c9e-8c0f-45ed-b0d1-06c2d7cac537

📥 Commits

Reviewing files that changed from the base of the PR and between 5b71547 and e815c23.

📒 Files selected for processing (2)
  • monai/transforms/spatial/dictionary.py
  • tests/transforms/test_rand_grid_distortiond.py

When _do_transform is False, convert_to_tensor was called on the
entire data dict, which fails when non-tensor values (e.g. ints,
strings) are present — causing "AttributeError: 'int' object has
no attribute 'numel'" in the DataLoader collate function.

Convert only the keyed tensor items instead, consistent with how
other dict transforms handle the no-transform case. Also return
dict unchanged when no keys match (first_key == ()).

Fixes Project-MONAI#8604

Signed-off-by: Heyang Qin <qysnn1@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/transforms/test_rand_grid_distortiond.py (1)

92-101: Consider documenting expected type conversion.

Per RandGridDistortiond.__call__ (lines 2300-2303 in dictionary.py), convert_to_tensor is called on keyed items even when no transform is applied. So result["img"] becomes a tensor, not numpy. The type_test=False masks this.

Adding an explicit type check or comment would clarify this expected behavior.

📝 Suggested clarification
         # non-tensor metadata should pass through unchanged
         self.assertEqual(result["extra_info"], 42)
         self.assertEqual(result["label_name"], "tumor")
+        # Note: convert_to_tensor is still called on keys, so img becomes tensor
         assert_allclose(result["img"], img, type_test=False)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/transforms/test_rand_grid_distortiond.py` around lines 92 - 101, Update
the test_no_transform_with_non_tensor_metadata test to assert the documented
type conversion behavior: note that RandGridDistortiond.__call__ invokes
convert_to_tensor on keyed items even when _do_transform is False, so "img" will
be converted to a tensor; modify the assertions to either check for tensor type
(e.g., isinstance(result["img"], torch.Tensor)) and compare values with an
appropriate array/tensor comparison, or add a clarifying comment explaining why
type_test=False is used and that result["img"] is expected to be a tensor due to
convert_to_tensor.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/transforms/test_rand_grid_distortiond.py`:
- Around line 92-101: Update the test_no_transform_with_non_tensor_metadata test
to assert the documented type conversion behavior: note that
RandGridDistortiond.__call__ invokes convert_to_tensor on keyed items even when
_do_transform is False, so "img" will be converted to a tensor; modify the
assertions to either check for tensor type (e.g., isinstance(result["img"],
torch.Tensor)) and compare values with an appropriate array/tensor comparison,
or add a clarifying comment explaining why type_test=False is used and that
result["img"] is expected to be a tensor due to convert_to_tensor.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 52024052-b702-43fc-9e97-978e58027360

📥 Commits

Reviewing files that changed from the base of the PR and between e815c23 and 517a713.

📒 Files selected for processing (1)
  • tests/transforms/test_rand_grid_distortiond.py

@HeyangQin HeyangQin force-pushed the fix/rand-grid-distortiond-no-transform branch from fe04817 to 7d5bf42 Compare March 22, 2026 06:48
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@monai/transforms/spatial/dictionary.py`:
- Around line 2312-2314: The early-return behavior should be consistent: when
first_key(d) == () the transform should return the input dict unchanged rather
than calling convert_to_tensor and recursing; update the affected transforms
(e.g., RandAffined, Rand2DElasticd, Rand3DElasticd, RandZoomd,
RandSimulateLowResolutiond) to match RandAxisFlipd/RandGridDistortiond by
returning d immediately when first_key == (), removing the convert_to_tensor(d,
...) call in that branch; ensure you only change the branch that checks
first_key(d) and keep all other processing (including calls to convert_to_tensor
for non-empty keys) intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9ffaa117-392b-4bbd-baa0-176907781f7f

📥 Commits

Reviewing files that changed from the base of the PR and between 517a713 and 7d5bf42.

📒 Files selected for processing (2)
  • monai/transforms/spatial/dictionary.py
  • tests/transforms/test_rand_grid_distortiond.py
✅ Files skipped from review due to trivial changes (1)
  • tests/transforms/test_rand_grid_distortiond.py

…l transforms

Unify the first_key == () handling in RandAffined, Rand2DElasticd,
Rand3DElasticd, RandZoomd, and RandSimulateLowResolutiond to return
the dict directly instead of calling convert_to_tensor on the entire
dict, which could inadvertently convert non-tensor metadata.

Signed-off-by: Heyang Qin <qysnn1@gmail.com>
Signed-off-by: Heyang Qin <qysnn1@gmail.com>
@HeyangQin HeyangQin force-pushed the fix/rand-grid-distortiond-no-transform branch from fcc4cf9 to bf00db8 Compare March 22, 2026 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AttributeError in DataLoader when using RandGridDistortiond transform

1 participant